/*************************************************
* Title：TinyToolKit
* Author：Opportunity 
* Describe：
* CreateTime：2020-08-20 16:12:42
* Version：1.0
* Modify Recorder：
*************************************************/

using System;
using System.Collections.Generic;
using System.Net;
using TinyToolKit;
using TinyToolKit.Network;
using UnityEngine;
using UnityEngine.UI;

public class LanChatCtr : MonoBehaviour
{
    public InputField ipInputField;
    public InputField portInputField;
    public InputField nameInputField;
    public InputField msgInputField;
    public Button createChatBtn;
    public Button enterChatBtn;
    public Button exitChatBtn;
    public Button sendBtn;
    public GameObject settingPanel;
    public GameObject infoPanel;
    public ChatScrollView chatScrollView;
    public Transform userList;
    public GameObject userItem;

    private TNetworkManager _networkManager;
    private TcpServerHelper _tcpServerHelper;
    private TcpClientHelper _tcpClientHelper;
    private bool _isServer;
    private Dictionary<string, GameObject> userMap;

    private void Start()
    {
        _networkManager = TinyTool.Instance.GetManager<TNetworkManager>();
        userMap = new Dictionary<string, GameObject>();
        settingPanel.SetActive(true);
        infoPanel.SetActive(false);
        sendBtn.interactable = false;

        //先开启服务端，再开启客户端
        createChatBtn.onClick.AddListener(() =>
        {
            if (_networkManager.CreateTcpServer(ipInputField.text, int.Parse(portInputField.text), 10, out _tcpServerHelper, OnConnectClient, OnDisconnectClient))
            {
                _isServer = true;
                _tcpServerHelper.AddHandleMsgMethod(RequestType.Player, new HandlePlayerMsg(_tcpServerHelper));
                CreateTcpClient();

                Debug.Log("聊天室创建成功");
            }
            else
            {
                Debug.Log("聊天室创建失败");
            }
        });

        enterChatBtn.onClick.AddListener(CreateTcpClient);
        sendBtn.onClick.AddListener(OnSendBtnClick);

        //先关闭客户端，再关闭服务器端
        exitChatBtn.onClick.AddListener(() =>
        {
            RemoveAllUserItem();
            _tcpClientHelper.Close();

            if (_isServer)
                _tcpServerHelper.Close();

            settingPanel.SetActive(true);
            infoPanel.SetActive(false);
        });
    }

    private void OnConnectClient(IPEndPoint point)
    {
        ProtocolBytes protocol = new ProtocolBytes();
        protocol.AddString(Enum.GetName(typeof(RequestType), RequestType.Player));
        protocol.AddString("AddUserItem");
        protocol.AddString(point.ToString());

        _tcpServerHelper?.Broadcast(protocol);
    }

    private void OnDisconnectClient(IPEndPoint point)
    {
        ProtocolBytes protocol = new ProtocolBytes();
        protocol.AddString(Enum.GetName(typeof(RequestType), RequestType.Player));
        protocol.AddString("RemoveUserItem");
        protocol.AddString(point.ToString());

        _tcpServerHelper?.Broadcast(protocol);
    }

    private void AddUserItem(bool isServer, string ip, string port)
    {
        GameObject item = Instantiate(userItem, userList);
        string address = $"{ip}:{port}";
        item.GetComponent<Text>().text = "成员：" + address;
        userMap.Add(address, item);
    }

    private void RemoveUserItem(string ip, string port)
    {
        string address = $"{ip}:{port}";
        if (userMap.TryGetValue(address, out GameObject item))
        {
            Destroy(item);
            userMap.Remove(address);
        }
    }

    private void RemoveAllUserItem()
    {
        foreach (var item in userMap)
        {
            Destroy(item.Value);
        }

        userMap.Clear();
    }

    private void CreateTcpClient()
    {
        if (_networkManager.CreateTcpClient(ipInputField.text, int.Parse(portInputField.text), out _tcpClientHelper, ConnSuccessCb))
        {
            _tcpClientHelper.AddEventListener("BroadcastMsg", BroadcastMsgCb);
            _tcpClientHelper.AddEventListener("AddUserItem", AddUserItemCb);
            _tcpClientHelper.AddEventListener("RemoveUserItem", RemoveUserItemCb);
        }
    }

    private void ConnSuccessCb()
    {
        sendBtn.interactable = true;
        settingPanel.SetActive(false);
        infoPanel.SetActive(true);
    }

    private void BroadcastMsgCb(ProtocolBase protocol)
    {
        ProtocolBytes prot = (ProtocolBytes) protocol;
        int start = 0;
        prot.GetString(start, ref start);
        prot.GetString(start, ref start);
        string msg = prot.GetString(start, ref start);

        chatScrollView.AddBubbleBox(msg);
    }

    private void AddUserItemCb(ProtocolBase protocol)
    {
        ProtocolBytes prot = (ProtocolBytes) protocol;
        int start = 0;
        prot.GetString(start, ref start);
        prot.GetString(start, ref start);
        string msg = prot.GetString(start, ref start);

        string[] strs = msg.Split(':');
        AddUserItem(_isServer, strs[0], strs[1]);
    }

    private void RemoveUserItemCb(ProtocolBase protocol)
    {
        ProtocolBytes prot = (ProtocolBytes) protocol;
        int start = 0;
        prot.GetString(start, ref start);
        prot.GetString(start, ref start);
        string msg = prot.GetString(start, ref start);

        string[] strs = msg.Split(':');
        RemoveUserItem(strs[0], strs[1]);
    }

    private void OnSendBtnClick()
    {
        string msg = nameInputField.text;
        msg = msg + "|" + msgInputField.text;

        if (msg.IsNullOrEmpty() == false)
        {
            ProtocolBytes protocol = new ProtocolBytes();
            protocol.AddString(Enum.GetName(typeof(RequestType), RequestType.Player));
            protocol.AddString("BroadcastMsg");
            protocol.AddString(msg);
            _tcpClientHelper.Send(protocol);
            //msgInputField.text = "";
        }
    }

    private void OnDisable()
    {
        _tcpClientHelper?.RemoveEventListener("BroadcastMsg", BroadcastMsgCb);
        _tcpClientHelper?.RemoveEventListener("AddUserItem", AddUserItemCb);
        _tcpClientHelper?.RemoveEventListener("RemoveUserItem", RemoveUserItemCb);
    }
}